global with sharing class HandlingAttachments{
    static String testVar = '';
    
    WebService static String retreiveContentType(String salesContractAttachmentId)
    {
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject attObj = new Attachment();

        Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(attObj);
        
        String[] attExpectedFields = new String[]{'Id','ContentType'}; 
        Set<String> allowedFields = dacu.getAccessibleFields(attObj, fieldMap, attExpectedFields);
        
        String constructSoql = '';
        if(!allowedFields.isEmpty())
        {
            constructSoql = 'Select ';
            for(String roField: allowedFields)
            {
                constructSoql += roField+', ';
            }
            constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
            constructSoql += ' from Attachment where Id = :salesContractAttachmentId';
            
            if(constructSoql.contains('Id'))
            {
                Attachment[] a = Database.query(constructSoql);//[SELECT Id, ContentType FROM Attachment a where a.Id = :salesContractAttachmentId];
                if(a.size() > 0)
                    return a[0].ContentType;
            }
        }       
    
        return 'null';
    }

    Webservice static Sales_Contract__c planDetails(ID planId)
    {
        Sales_Contract__c planDetail = null;
        
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject scObj = new Sales_Contract__c();

        Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(scObj);
        
        String[] scExpectedFields = new String[]{'Id','Name','FirstName__c','LastName__c','UserID__c','UserRoleId__c','UserRoleName__c','Name1__c','Name2__c','Name3__c','Name4__c','Name5__c','Name6__c','Name7__c','Name8__c','Name9__c','Name10__c','Name11__c','Name12__c','Name13__c','Name14__c','Name15__c','Name16__c','Name17__c','Name18__c','Name19__c','Name20__c','Name21__c','Name22__c','Name23__c','Name24__c','Name25__c','Name26__c','Name27__c','Name28__c','Name29__c','Name30__c','Value1__c','Value2__c','Value3__c','Value4__c','Value5__c','Value6__c','Value7__c','Value8__c','Value9__c','Value10__c','Value11__c','Value12__c','Value13__c','Value14__c','Value15__c','Value16__c','Value17__c','Value18__c','Value19__c','Value20__c','Value21__c','Value22__c','Value23__c','Value24__c','Value25__c','Value26__c','Value27__c','Value28__c','Value29__c','Value30__c'}; 
        Set<String> allowedFields = dacu.getAccessibleFields(scObj, fieldMap, scExpectedFields);
        
        String constructSoql = '';
        if(!allowedFields.isEmpty())
        {
            constructSoql = 'Select ';
            for(String roField: allowedFields)
            {
                constructSoql += roField+', ';
            }
            constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
            constructSoql += '  FROM Sales_Contract__c sc where sc.Id = :planId';
            
            if(constructSoql.contains('Id'))
            {
                planDetail = Database.query(constructSoql);//[SELECT Id, Name, FirstName__c, LastName__c, UserID__c, UserRoleId__c, UserRoleName__c, Name1__c, Name2__c, Name3__c, Name4__c, Name5__c, Name6__c, Name7__c, Name8__c, Name9__c, Name10__c, Name11__c, Name12__c, Name13__c, Name14__c, Name15__c, Name16__c, Name17__c, Name18__c, Name19__c, Name20__c, Name21__c, Name22__c, Name23__c, Name24__c, Name25__c, Name26__c, Name27__c, Name28__c, Name29__c, Name30__c, Value1__c, Value2__c, Value3__c, Value4__c, Value5__c, Value6__c, Value7__c, Value8__c, Value9__c, Value10__c, Value11__c, Value12__c, Value13__c, Value14__c, Value15__c, Value16__c, Value17__c, Value18__c, Value19__c, Value20__c, Value21__c, Value22__c, Value23__c, Value24__c, Value25__c, Value26__c, Value27__c, Value28__c, Value29__c, Value30__c FROM Sales_Contract__c sc where sc.Id=:planId];
                return planDetail;
            }
        }
        return null;
    }

    WebService static String retreiveBody(String salesContractAttachmentId)
    {
        String body = '';

        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject attObj = new Attachment();

        Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(attObj);
        
        String[] attExpectedFields = new String[]{'Id','Body'}; 
        Set<String> allowedFields = dacu.getAccessibleFields(attObj, fieldMap, attExpectedFields);
        
        String constructSoql = '';
        if(!allowedFields.isEmpty())
        {
            constructSoql = 'Select ';
            for(String roField: allowedFields)
            {
                constructSoql += roField+', ';
            }
            constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
            constructSoql += ' from Attachment where Id = :salesContractAttachmentId';
            
            if(constructSoql.contains('Id'))
            {
                Attachment[] a = Database.query(constructSoql);//[SELECT Id, Body FROM Attachment a where a.Id = :salesContractAttachmentId];
                Blob blobContent = a[0].Body;
            
                body = blobContent.toString();
                 
                return body;
                
            }
        }
        return 'null';
    }
    
    
    //finds whether a Template has Attachments are not.   
    Webservice static Boolean hasAttachments(ID templateId)
    {
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject attObj = new Attachment();

        Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(attObj);
        
        String[] attExpectedFields = new String[]{'Id'}; 
        Set<String> allowedFields = dacu.getAccessibleFields(attObj, fieldMap, attExpectedFields);
        
        String constructSoql = '';
        if(!allowedFields.isEmpty())
        {
            constructSoql = 'Select ';
            for(String roField: allowedFields)
            {
                constructSoql += roField+', ';
            }
            
            constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
            constructSoql += ' from Attachment where ParentId = :templateId ';

            if(constructSoql.contains('Id'))
            {
                Attachment[] att = Database.query(constructSoql);//[select Id from Attachment where parentid = :templateId];
                if(att.size() > 0)
                    return true;
            }
            
            
        }
        
        return false;
    }//end of hasAttachments(ID)

    WebService static String updateStatus(String salesContractId)
    {
        Sales_Contract__c[] sc = new Sales_Contract__c[]{};
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject scObj = new Sales_Contract__c();

        Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(scObj);
        
        //Note: Whenever a new Custom field has to be updated, add it to the below Set.
        //Reason: The size of the below set will be compared with the size of the filtered set 
        Set<String> scExpectedFields = new Set<String>{'Status__c','DocMerged__c','DateViewed__c'}; 
        
        //get the filtered updateable fields
        Set<String> allowedFields = dacu.getFilteredUpdateableFields(fieldMap, scExpectedFields);
        String constructSoql = '';

        //Enters only if the filteredList size is equivalent to the size of expected updateable fields List 
        if(allowedFields.size() == scExpectedFields.size())
        {
            constructSoql = 'Select Id, ';
            for(String roField: allowedFields)
            {
                constructSoql += roField+', ';
            }
            constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
            constructSoql += '  FROM Sales_Contract__c  where Id = :salesContractId ';
            
            if(constructSoql.contains(','))
            {
                sc = Database.query(constructSoql);//[SELECT Id, Status__c, DocMerged__c, DateViewed__c, User_ID__c, Name1__c, Name2__c, Name3__c, Name4__c, Name5__c, Name6__c, Name7__c, Name8__c, Name9__c, Name10__c, Name11__c, Name12__c, Name13__c, Name14__c, Name15__c, Name16__c, Name17__c, Name18__c, Name19__c, Name20__c, Name21__c, Name22__c, Name23__c, Name24__c, Name25__c, Name26__c, Name27__c, Name28__c, Name29__c, Name30__c, Value1__c, Value2__c, Value3__c, Value4__c, Value5__c, Value6__c, Value7__c, Value8__c, Value9__c, Value10__c, Value11__c, Value12__c, Value13__c, Value14__c, Value15__c, Value16__c, Value17__c, Value18__c, Value19__c, Value20__c, Value21__c, Value22__c, Value23__c, Value24__c, Value25__c, Value26__c, Value27__c, Value28__c, Value29__c, Value30__c FROM Sales_Contract__c s where s.Id = :salesContractId];

                if(sc.size() == 0)
                    return 'null';
                else
                {
                    //Store the expected updated fields and their values
                    Map<String, Object> fieldsValMap = new Map<String, Object>();
                    fieldsValMap.put('Status__c', 'Viewed');
                    fieldsValMap.put('DocMerged__c', true);
                    fieldsValMap.put('DateViewed__c', System.now());

                    scObj = sc[0];
                    
                    //allowedFields contains the filtered updateable fields
                    for(String s: allowedFields)
                    {
                        scObj.put(s, fieldsValMap.get(s));
                    }
                    
                    try
                    {
                        if(testVar == '')
                        {
                            update scObj;//update sc;
                        }
                    }
                    catch(DmlException d)
                    {
                        return d.getMessage(); 
                    }
                    Sales_Contract__History history = new Sales_Contract__History(ParentId = salesContractId);
                }   

            }
        }   
        if(sc.size() == 0)
            return 'null';
        else
            return 'Updated Successfully';    
    }
    
    WebService static String updateStatusForNonE(String salesContractName)
    {  
	    CallidusPlanControl__c cpc = CallidusPlanControl__c.getInstance(UserInfo.getUserId());
	    if(cpc != null)
	    {
	        if(cpc.can_accept__c == true)
	        {
	            Schema.DescribeSobjectResult dsr = Sales_Contract__c.sObjectType.getDescribe();
		        Schema.DescribeFieldResult dfrName = Sales_Contract__c.Name.getDescribe();
		        Schema.DescribeFieldResult dfrStatus = Sales_Contract__c.Status__c.getDescribe();
		        Schema.DescribeFieldResult dfrDateAccepted = Sales_Contract__c.DateAccepted__c.getDescribe();
		        
		        if(dsr.isAccessible() && dsr.isUpdateable() && dfrName.isAccessible() && dfrStatus.isAccessible() && dfrStatus.isUpdateable() && dfrDateAccepted.isAccessible() && dfrDateAccepted.isUpdateable())
		        {       
		            Sales_Contract__c[] sc = [SELECT Id, FirstName__c, LastName__c, AttachmentID__c, AttachmentIDVals__c, Status__c, Name, DateAccepted__c, UserID__c, OwnerId, Email_Notification_1__c, Email_Notification_2__c, Email_Notification_3__c, Can_Accept_Plan__c from Sales_Contract__c s where s.Name = :salesContractName];
		            if(sc.size() == 0)
		            {
		               return 'Sales Contract Id does not exist';
		            }
		            try{
		                if(sc[0]!= null)
		                {
		                    String[] attachmentIdList = sc[0].AttachmentIDVals__c.split(',');
		                    Attachment[] queryAttachment = [select Body, Id, Name, ContentType from Attachment where id in :attachmentIdList];
		                    String attachmentNamesValue = '';
		                    Messaging.EmailFileAttachment[] allAttachments = new  Messaging.EmailFileAttachment[queryAttachment.size()]; 
		                    for(integer i=0;i<queryAttachment.size();i++)
		                    {
		                        Messaging.EmailFileAttachment fileAttachment = new Messaging.EmailFileAttachment();
		                        fileAttachment.setBody(queryAttachment[i].Body);
		                        fileAttachment.setFileName(queryAttachment[i].Name);
		                        allAttachments[i] =  fileAttachment;
		                        attachmentNamesValue += queryAttachment[i].Name+'; ';
		                    }
		                    attachmentNamesValue = attachmentNamesValue.substring(0, attachmentNamesValue.length() - 2);
		                    
		                    sc[0].Accepted_Documents__c = attachmentNamesValue;
		                    sc[0].Status__c = 'Accepted';
		                    sc[0].DateAccepted__c = Datetime.now();
		                    update sc;
		                    
		                    EmailTemplate e = [select Id,Name,Subject,body from EmailTemplate where name like :'Callidus_Plan_Document_Acceptance_Mail'];
		                                                              
		                    Messaging.SingleEmailMessage[] mailList = new Messaging.SingleEmailMessage[]{};
		
		                    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();                 
		                    mail.saveAsActivity = false;
		                    mail.setFileAttachments(allAttachments);
		                    mail.setTargetObjectId(sc[0].UserId__c);
		                    mail.setTemplateId(e.Id);
		                    mail.setWhatId(sc[0].Id);
		                    mail.setUseSignature(false);
		                    mail.setSaveAsActivity(false);
		                    mailList.add(mail);
		
		                    mail = new Messaging.SingleEmailMessage();                  
		                    mail.saveAsActivity = false;
		                    mail.setFileAttachments(allAttachments);
		                    mail.setTargetObjectId(sc[0].OwnerId);
		                    mail.setTemplateId(e.Id);
		                    mail.setWhatId(sc[0].Id);
		                    mail.setUseSignature(false);
		                    mail.setSaveAsActivity(false);
		                    mailList.add(mail);
		                        
		                    // Send the email
		                    Messaging.sendEmail(mailList);
		                }                              
		           }
		           catch(Exception e){return e.getMessage();}
		        }
	        }
	    }
        return 'success';
    }

    static testMethod void testHelloWorld() 
    {
        Sales_Contract__c sc = new Sales_Contract__c();
        Template__c t = new Template__c();
        Test.startTest();
        insert sc;
        Sales_Contract__c[] scT = [select id from Sales_Contract__c where id = :sc.Id];
        system.assertEquals(sc.id, scT[0].id);
                
        testVar = 'Published';
        system.assertEquals('Updated Successfully', updateStatus(sc.Id));

        insert t;
        Template__c[] tempT = [select id from Template__c where id = :t.id];
        system.assertEquals(t.id, tempT[0].id);
        
        Attachment a = new Attachment(name = 'Test', Body = Blob.valueOf('<html><body>This is an Attachment</body></html>'), ParentId = t.Id);
        insert a;
        Attachment[] attT = [select name, Body, Parentid from Attachment where id = :a.id];
        system.assertEquals(a.name, attT[0].name);
        system.assertEquals(a.Body.toString(), attT[0].Body.toString());
        system.assertEquals(a.ParentId, attT[0].ParentId);
        
        system.assertEquals(a.Body.toString(), HandlingAttachments.retreiveBody(a.Id));
        
        system.assertEquals('Updated Successfully', HandlingAttachments.updateStatus(sc.Id));
        system.assertEquals(true, hasAttachments(t.Id));
        HandlingAttachments.retreiveContentType(a.Id);
        sc = new Sales_Contract__c(FirstName__c = 'Ryan');
        insert sc;
        planDetails(sc.id);

        system.assertEquals('Ryan', sc.FirstName__c);      
        test.stopTest();
    }

    static testMethod void dacuTestCase() 
    {
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject sObj = new CallidusDataSOurce__c();
        Map<String, Schema.Sobjectfield> fieldsMap = dacu.getFieldMap(sObj);
        String[] expectedFieldMap = new String[]{'Id','Name'};
        Set<String> allowedFields = dacu.getAccessibleFields(sObj, fieldsMap, expectedFieldMap);
        Set<String> filteredList = dacu.getFilteredCreateableFields(fieldsMap, allowedFields);
        filteredList = dacu.getFilteredUpdateableFields(fieldsMap, allowedFields);
        system.assertEquals('success', dacu.isCreateableObjectByUser(sObj));
        system.assertEquals('success', dacu.isUpdateableObjectByUser(sObj));
        system.assertEquals('success', dacu.isDeleteableObjectByUser(sObj));
        dacu.pageMessage(sobj, 'create');
    }
}